﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "PropertyComponentTypeWidget.h"
#include "PropertyWidget.h"
#include "PropertyComboxGroups.h"
#include "PropertyComponentTypeEdit.h"

#include <QHBoxLayout>


#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
namespace PropertyWidget
{
    CComponentTypeGroup::CComponentTypeGroup( int64_t uniqueID, const QString &groupName, const QString &groupIconPath )
        :m_uniqueID(uniqueID), m_groupName(groupName), m_groupIconPath(groupIconPath)
    {

    }

    const QString& CComponentTypeGroup::GroupName() const
    {
        return m_groupName;
    }

    const QString& CComponentTypeGroup::GroupIconPath() const
    {
        return m_groupIconPath;
    }

    int64_t CComponentTypeGroup::UniqueID() const
    {
        return m_uniqueID;
    }
    
    CComponentTypeItem::CComponentTypeItem( CComponentTypeGroup *owner, int64_t uniqueID, const QString & name, const QString & iconFileName )
        :m_pOwner(owner), m_uniqueID(uniqueID), m_name(name), m_iconFileName(iconFileName)
    {

    }

    CComponentTypeGroup *CComponentTypeItem::Owner() const
    {
        return m_pOwner;
    }

    const QString &CComponentTypeItem::Name() const
    {
        return m_name;
    }

    const QString &CComponentTypeItem::IconFileName() const
    {
        return m_iconFileName;
    }

    int64_t CComponentTypeItem::UniqueID() const
    {
        return m_uniqueID;
    }
    
    CComponentTypeWidget::CComponentTypeWidget(QWidget *pParent)
        : QFrame(pParent),
        m_upComboxGroups(nullptr),
        m_upComponentTypeEditFrame(nullptr)
    {
        setFixedHeight(63); //设置固定高度63px
        setStyleSheet("PropertyWidget--CComponentTypeWidget{border: 1px solid gray;}");

        // 构件类型分组组合框
        m_upComboxGroups = std::unique_ptr<QComboxGroups>(new QComboxGroups(this));
        m_upComboxGroups->setObjectName("ComboBoxTypeGroups");
        m_upComboxGroups->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        connect(m_upComboxGroups.get(), SIGNAL(SelectChangedComponentType(const CComponentTypeItem *)), this, SLOT(OnSelectComponentType(const CComponentTypeItem *)));

        // 构件类型编辑
        m_upComponentTypeEditFrame = std::unique_ptr<CComponentTypeEdit>(new CComponentTypeEdit(this));
        m_upComponentTypeEditFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        

        //布局器整体水平布局CComponentType
        QHBoxLayout *pHBoxLayout = new QHBoxLayout(this);
        pHBoxLayout->setContentsMargins(0,0,0,0);
        pHBoxLayout->setSpacing(0);
        pHBoxLayout->addWidget(m_upComboxGroups.get());
        pHBoxLayout->addWidget(m_upComponentTypeEditFrame.get());
       
    }

    CComponentTypeWidget::~CComponentTypeWidget()
    {
        m_ComponentTypeItems.clear();
        m_ComponentTypeGroups.clear();
    }

    CComponentTypeGroup *CComponentTypeWidget::AddComponentTypeGroup( int groupIndex, int64_t uniqueID,
        const QString& groupName, const QString& groupIconPath)
    {
        //索引不在有效范围不能添加 范围 [ 0, size() ]
        if (groupIndex < 0 || groupIndex > (int)m_ComponentTypeGroups.size())
        {
            return nullptr;
        }

        std::unique_ptr<CComponentTypeGroup> pComponentTypeGroup = std::unique_ptr<CComponentTypeGroup>(new CComponentTypeGroup(uniqueID, groupName,groupIconPath));
        m_ComponentTypeGroups.insert(m_ComponentTypeGroups.begin() + groupIndex, std::move(pComponentTypeGroup));
        std::vector<std::unique_ptr<CComponentTypeItem>> cmptTypeItemGroup;
        m_ComponentTypeItems[pComponentTypeGroup.get()] = std::move(cmptTypeItemGroup);
        m_upComboxGroups->AddItemsGroup(groupIndex, m_ComponentTypeGroups[groupIndex].get());

        return m_ComponentTypeGroups[groupIndex].get();
    }

    CComponentTypeGroup *CComponentTypeWidget::GetComponentTypeGroupByUniqueID( int64_t uniqueID ) const
    {
        for (int i = 0; i < (int)m_ComponentTypeGroups.size(); ++i)
        {
            if (m_ComponentTypeGroups.at(i)->UniqueID() == uniqueID)
            {
                return m_ComponentTypeGroups.at(i).get();
            }
        }
        return nullptr;
    }

    CComponentTypeGroup *CComponentTypeWidget::GetComponentTypeGroupByIndex( int groupIndex ) const
    {
        if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
        {
            return nullptr;
        }
        return m_ComponentTypeGroups[groupIndex].get();
    }

    int CComponentTypeWidget::ComponentTypeGroupsCount() const
    {
        return (int)m_ComponentTypeGroups.size();
    }

    bool CComponentTypeWidget::RemoveComponentTypeGroup( int groupIndex )
    {
        if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
        {
            return false;
        }

        bool rst = m_upComboxGroups->RemoveItemsGroup(groupIndex);

        CComponentTypeGroup * pComponentTypeGroup = m_ComponentTypeGroups[groupIndex].get();
        m_ComponentTypeGroups.erase(m_ComponentTypeGroups.begin() + groupIndex);
        std::vector<std::unique_ptr<CComponentTypeItem>>& componentTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
        componentTypeItems.clear();
        m_ComponentTypeItems.erase(pComponentTypeGroup);

        return rst;
    }

    bool CComponentTypeWidget::RemoveAllComponentTypeGroup()
    {
        if (m_ComponentTypeGroups.empty() != true)
        {
            bool rst = m_upComboxGroups->RemoveAllItemsGroup();
            m_ComponentTypeGroups.clear();
            m_ComponentTypeItems.clear();
            QPixmap pic(QStringLiteral(":/images/GBM.png"));
            QIcon icon(pic);
            m_upComboxGroups->SetDefaultComboBox(QString::fromStdWString(L""), icon);
            return rst;
        }
        return false;
    }

    CComponentTypeItem * CComponentTypeWidget::AddComponentType( int groupIndex, int indexInGroup, int64_t uniqueID,
        QString const &name, QString const &cmptTypeIconPath)
    {
        if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
        {
            return nullptr;
        }

        CComponentTypeGroup* pComponentTypeGroup = m_ComponentTypeGroups[groupIndex].get();
        std::vector<std::unique_ptr<CComponentTypeItem>> & componentTypeItem = m_ComponentTypeItems[pComponentTypeGroup];
        std::unique_ptr<CComponentTypeItem> pComponentTypeItemAdd = std::unique_ptr<CComponentTypeItem>(new CComponentTypeItem(pComponentTypeGroup, uniqueID, name, cmptTypeIconPath));
        CComponentTypeItem* pTypeItem = pComponentTypeItemAdd.get();
        if (indexInGroup < 0 || indexInGroup >= (int)componentTypeItem.size())//索引不在有效范围就追加
        {
            componentTypeItem.push_back(std::move(pComponentTypeItemAdd));
        }
        else
        {
            componentTypeItem.insert(componentTypeItem.begin() + indexInGroup, std::move(pComponentTypeItemAdd));
        }

        m_upComboxGroups->AddItem(groupIndex, indexInGroup, pTypeItem);
        return pComponentTypeItemAdd.get();
    }

    CComponentTypeItem *CComponentTypeWidget::GetComponentTypeByIndex( int groupIndex, int indexInGroup )
    {
        if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
        {
            return nullptr;
        }
        
        CComponentTypeGroup* pComponentTypeGroup = m_ComponentTypeGroups[groupIndex].get();
        std::vector<std::unique_ptr<CComponentTypeItem>> & componentTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
        if (indexInGroup < 0 || indexInGroup >= (int)componentTypeItems.size())
        {
            return nullptr;
        }
        return componentTypeItems[indexInGroup].get();
    }

    CComponentTypeItem *CComponentTypeWidget::GetComponentTypeByUniqueID(int64_t uniqueID)
    {
        for (int i = 0; i < (int)m_ComponentTypeGroups.size(); ++i)
        {
            CComponentTypeGroup* pComponentTypeGroup = m_ComponentTypeGroups[i].get();
            int typeCount = (int)m_ComponentTypeItems[pComponentTypeGroup].size();
            for (int j = 0; j < typeCount; ++j)
            {
                if (m_ComponentTypeItems[pComponentTypeGroup].at(j)->UniqueID() == uniqueID)
                {
                    return m_ComponentTypeItems[pComponentTypeGroup].at(j).get();
                }
            }
        }

        return nullptr;
    }

    bool CComponentTypeWidget::RemoveComponentType( int groupIndex, int indexInGroup)
    {
        if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
        {
            return false;
        }

        CComponentTypeGroup * pComponentTypeGroup = m_ComponentTypeGroups[groupIndex].get();
        std::vector<std::unique_ptr<CComponentTypeItem>> & componentTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
        if (indexInGroup < 0 || indexInGroup >= (int)componentTypeItems.size())
        {
            return false;
        }

        bool rst = m_upComboxGroups->RemoveItem(groupIndex,indexInGroup);

        //同步数据
        componentTypeItems.erase(componentTypeItems.begin() + indexInGroup);
        if (componentTypeItems.size() < 1)
        {
            m_ComponentTypeGroups.erase(m_ComponentTypeGroups.begin() + groupIndex);
            m_ComponentTypeItems.erase(pComponentTypeGroup);
        }
        return rst;
    }

    bool CComponentTypeWidget::setCurrentComponentType( int groupindex, int indexInGroup )
    {
        if (nullptr != m_upComboxGroups)
        {
            m_curGroupTypeIndex = groupindex;
            m_curTypeIndex = indexInGroup;
            m_upComponentTypeEditFrame->setDisabled(false);
            return m_upComboxGroups->setCurrentItem(groupindex,indexInGroup);
        }
        return false;
    }

    void CComponentTypeWidget::GetCurrentComponentType(int &groupIndex, int &indexInGroup)
    {
        groupIndex = m_curGroupTypeIndex;
        indexInGroup = m_curTypeIndex;
    }

    void CComponentTypeWidget::setComponentTypeAddButtonIcon(const QString & iconFileName )
    {
        if (m_upComponentTypeEditFrame)
        {
            m_upComponentTypeEditFrame->setComponentTypeAddButtonIcon(iconFileName);
        }
    }

    void CComponentTypeWidget::setComponentTypeModifyButtonIcon(const QString & iconFileName )
    {
        if (m_upComponentTypeEditFrame)
        {
            m_upComponentTypeEditFrame->setComponentTypeModifyButtonIcon(iconFileName);
        }
    }

    void CComponentTypeWidget::setEnableComponentTypeAddButton(bool isEnable)
    {
        if (m_upComponentTypeEditFrame)
        {
            m_upComponentTypeEditFrame->setEnableComponentTypeAddButton(isEnable);
        }
    }

    void CComponentTypeWidget::setEnableComponentTypeModifyButton(bool isEnable)
    {
        if (m_upComponentTypeEditFrame)
        {
            m_upComponentTypeEditFrame->setEnableComponentTypeModifyButton(isEnable);
        }
    }

    void CComponentTypeWidget::setEnableComponentTypeChangeComboxGroup(bool isEnable)
    {
        if (m_upComboxGroups)
        {
            m_upComboxGroups->SetEnableComponentTypeChangeComboBox(isEnable);
        }
    }
    void CComponentTypeWidget::DisplayMultiValState(const QString &name, const QString & typeIconPath)
    {
        QPixmap pic(typeIconPath);
        QIcon icon(pic);
        m_upComboxGroups->SetDefaultComboBox(name, icon);
    }

    void CComponentTypeWidget::OnComponentTypeAddButtonClick()
    {
        emit TypeAddButtonClick();
    }

    void CComponentTypeWidget::OnComponentTypeModifyButtonClick()
    {
        emit TypeModifyButtonClick();
    }

    void CComponentTypeWidget::OnSelectComponentType(const CComponentTypeItem *pComponentTypeItem)
    {
        emit ComponentTypeChanged(pComponentTypeItem);
    }
}
